/*
 * RAM class represents a physical addressable memory component
 * RAM subscribes to the Memory interface
 * A giant array of Bytes
 * */

package system.memory;

import java.lang.reflect.Array;

import cpu.components.MemoryUnit;
import cpu.datatypes.*;
import cpu.datatypes.Byte;
import cpu.interfaces.*;
import cpu.components.CacheUnit;


public class RAM implements Memory {
	private MemoryUnit memorycontroller;
	private CacheUnit cachecontroller;
	
	private static final int LENGTH = 16384;
	private static final int BANKS = 2;
	//private Cache cache;
	private Byte[][] RAMARRAY=new Byte[BANKS][LENGTH];
	
	public RAM( MemoryUnit memorycontroller, CacheUnit cachecontroller ) {
		for (int bank =0;bank<BANKS;bank++)
		{
			for(int i=0;i<LENGTH;i++)
			{
				RAMARRAY[bank][i]=new Byte();
			}
		}
		
		this.memorycontroller = memorycontroller;
		this.cachecontroller = cachecontroller;
		//cache= new  Cache(cachecontroller);
	}
	//this is the new code:

	public void get( ) {
		if(!memorycontroller.caching) {
			//int add=controller.MAR.toJavaInt( );
			int add=memorycontroller.MAR.toSignedInteger( );
			if(add< 2*LENGTH )
			{
				int bank=(int)add / (int)LENGTH;
				int offset=(int)add % (int)LENGTH;
				
				if (offset==LENGTH-1)// check the value of the index if it reaches the end where we can not the word in one bank
				{
					if (bank ==0 )// we split the word between the two banks
					{
						memorycontroller.MBR.byteLow.fromByte( RAMARRAY[bank][offset] );
						memorycontroller.MBR.byteHigh.fromByte( RAMARRAY[bank+1][0] );
					}
					else 
						{ 
						; 
						// if its more than # of banks handle error
						// throw system error
						//MFR=0
						}
				}		
				else 
				{
					memorycontroller.MBR.byteLow.fromByte( RAMARRAY[bank][offset] );
					memorycontroller.MBR.byteHigh.fromByte( RAMARRAY[bank][offset+1] );
				}
			}
			else 
			{
				// if its more than # of banks handle error
				// throw system error
				//MFR=0
			}
			
			// controller.MBR <- Memory(controller.MAR)
		} else {
			//cache code here
			cachecontroller.MAR.fromRegister(memorycontroller.MAR);
			cachecontroller.get();
		}
	}
	public void put( ) {
		 if(!memorycontroller.caching) {
			// update ram - if caching this is a write-through
			int add=memorycontroller.MAR.toSignedInteger( );
			//int add=controller.MAR.toJavaInt( );
			if(add< 2*LENGTH )
			{
				int bank=(int)add/(int)LENGTH;
				int offset=(int) add%LENGTH;
				// It will store the bytelow first and then the bytehigh
				
				if (offset == LENGTH-1 )// check the value of the offset if it reaches the end where we can not the word in one bank
				{
					if (bank == 0  )// we split the word between the two banks
					{
						;//handle the memory allocation 
						//MSR 
						RAMARRAY[bank][offset].fromByte( memorycontroller.MBR.byteLow );
						RAMARRAY[bank+1][0].fromByte( memorycontroller.MBR.byteHigh );
						
					}
					else //otherwise MFR 
						{ 
						; //MFR
						}
				}		
				else 
				{
					RAMARRAY[bank][offset].fromByte( memorycontroller.MBR.byteLow );
					RAMARRAY[bank][offset+1].fromByte( memorycontroller.MBR.byteHigh );
				}
			}
			else
			{
				; 
				// if its more than # of banks handle error
				// throw system error
				//MFR=0
			}
			
		}
	
		else
		{
			// update the cache
			// update ram - if caching this is a write-through
			//int add=memorycontroller.MAR.toSignedInteger( );
			cachecontroller.MAR.fromRegister(memorycontroller.MAR);
			cachecontroller.MBR.fromRegister(memorycontroller.MBR);
			cachecontroller.put();
			
		}
		
	}
	
}
